package ym.ecrm.core.service.systemManagement.impl;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

//import org.objectweb.asm.xwork.tree.IntInsnNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import ym.ecrm.core.common.exception.MessageException;
import ym.ecrm.core.common.util.DataValidation;
import ym.ecrm.core.common.util.Node;
import ym.ecrm.core.common.util.Pager;
import ym.ecrm.core.dao.systemManagement.IOrganizationDAO;
import ym.ecrm.core.dao.systemManagement.IResourceDAO;
import ym.ecrm.core.dao.systemManagement.IRoleDAO;
import ym.ecrm.core.dao.systemManagement.IUserDAO;
import ym.ecrm.core.domain.systemManagement.Organization;
import ym.ecrm.core.domain.systemManagement.Resource;
import ym.ecrm.core.domain.systemManagement.Role;
import ym.ecrm.core.domain.systemManagement.User;
import ym.ecrm.core.dto.systemManagement.OrganizationDTO;
import ym.ecrm.core.dto.systemManagement.ResourceDTO;
import ym.ecrm.core.dto.systemManagement.RoleDTO;
import ym.ecrm.core.dto.systemManagement.RoleQueryConditionDTO;
import ym.ecrm.core.dto.systemManagement.UserDTO;
import ym.ecrm.core.dto.systemManagement.UserQueryConditionDTO;
import ym.ecrm.core.service.systemManagement.ISystemService;

@Service("systemService")
@Transactional
public class SystemService implements ISystemService {

	@Autowired
	private IUserDAO userDAO;
	@Autowired
	private IRoleDAO roleDAO;
	@Autowired
	private IResourceDAO resourceDAO;
	@Autowired
	private IOrganizationDAO organizationDAO;

	@Override
	public UserDTO login(String userName, String password)
			throws MessageException {
		User user = (User) userDAO.findUniqueBy("userName", userName);
		if (user == null) {
			throw new MessageException("用户名不存在");
		}

		System.out.println(user.getPassword());
		System.out.println(password);
		if (user.getPassword().equals(password)) {
			UserDTO userDTO = new UserDTO();
			UserDTO.entity2dto(user, userDTO);
			return userDTO;
		} else {
			throw new MessageException("密码不正确");
		}
	}

	@Override
	public boolean changePassword(Long userId, String password) {
		User user = userDAO.load(userId);
		user.setPassword(password);
		userDAO.update(user);
		return true;
	}

	@Override
	public boolean changeRole(Serializable userId, List<Long> roles)
			throws MessageException {
		User user = userDAO.get(userId);
		// 1l为角色（Guest）的id，而Guest不能移除，
		if (!roles.contains(1l)) {
			throw new MessageException("用户必须具有缺省角色（Guest）");
		}
		Set<Role> set = new HashSet<Role>();
		for (int i = 0; i < roles.size(); i++) {
			set.add(roleDAO.get(roles.get(i)));
		}
		user.setRoles(set);
		return true;
	}

	@Override
	public UserDTO createUser(UserDTO userDTO) throws MessageException {
	
		// 系统自动创建用户密码 缺省为系统用户名称字符串
		if (userDTO.getPassword() == null || userDTO.getPassword().equals("")) {
			userDTO.setPassword(userDTO.getUserName());
		}
	
		User user = new User();
		UserDTO.dto2entity(userDTO, user);
	
		DataValidation.isNullOrBlank(user.getUserCode(), "用户编号不能为空");
		DataValidation.isNullOrBlank(user.getUserName(), "用户名不能为空");
		DataValidation.isNullOrBlank(user.getState(), "用户状态不能为空");
		if (userDAO.findUniqueBy("userName", userDTO.getUserName()) != null) {
			throw new MessageException("用户名无效，该用户名已经存在");
		}
		if (userDAO.findUniqueBy("userCode", userDTO.getUserCode()) != null) {
			throw new MessageException("用户编无效，该用户编号已经存在");
		}
		DataValidation.isPhoneNumber(user.getMobilePhone(), "无效的手机号码");
		DataValidation.isPhoneNumber(user.getPhone(), "无效的电话号码");
		DataValidation.isEmail(user.getEmailAddress(), "无效的Email地址");
		
		userDAO.save(user);
		userDTO.setUserId(user.getId());
		// 缺少部门的关联部分
		return userDTO;
	}

	@Override
	public boolean createRole(RoleDTO roleDTO) throws MessageException {
		
		DataValidation.isNullOrBlank(roleDTO.getRoleCode(), "角色编号不能为空");
		DataValidation.isNullOrBlank(roleDTO.getRoleName(), "角色名不能为空");
		if (roleDAO.findUniqueBy("roleCode", roleDTO.getRoleCode()) != null) {
			throw new MessageException("输入的角色编号重复");
		}
		if (roleDAO.findUniqueBy("roleName", roleDTO.getRoleName()) != null) {
			throw new MessageException("输入的角色名称有重复");
		}
		Role role = new Role();
		RoleDTO.dto2entity(roleDTO, role);
		roleDAO.save(role);
		return true;
	}

	@Override
	public boolean createOrganization(OrganizationDTO organizationDTO) throws MessageException {
		Organization organization = new Organization();
		OrganizationDTO.dto2entity(organizationDTO, organization);
		
		DataValidation.isNullOrBlank(organization.getOrganizationCode(),"组织结构编号不能为空");
		DataValidation.isNullOrBlank(organization.getName(),"组织结构名称不能为空");
		if(organizationDAO.findUniqueBy("organizationCode", organizationDTO.getOrganizationCode()) != null){
			throw new MessageException("组织结构编号已存在");
		}
		DataValidation.isPhoneNumber(organization.getTelephone(), "电话号码无效");
		DataValidation.isPhoneNumber(organization.getFax(), "传真号码无效");
		
		organizationDAO.save(organization);
		Organization parent = organizationDAO.get(organizationDTO.getOrganizationId());
		organization.setParent(parent);
		organizationDAO.update(organization);
		return true;
	}

	@Override
	public void createResource(ResourceDTO resourceDTO) {
		Resource resource = new Resource();
		ResourceDTO.dto2entity(resourceDTO, resource);
		resourceDAO.save(resource);
	}

	@Override
	public void deleteUser(Serializable id) {
		userDAO.delete(id);
	}

	@Override
	public void deleteUsers(List<Long> idList) {
		for (int i = 0; i < idList.size(); i++) {
			userDAO.delete(idList.get(i));
		}
	}

	@Override
	public boolean deleteRole(Serializable id) {
		roleDAO.delete(id);
		return true;
	}

	@Override
	public boolean deleteOrganization(Serializable id) {
		Organization organization = organizationDAO.load(id);
		Organization parentOrganization = organization.getParent();
		if (parentOrganization != null) {
			Set<User> members = new HashSet<User>();
			findOrganizationMember(organization, members);
			parentOrganization.getMember().addAll(members);
			organizationDAO.update(parentOrganization);
			Iterator it = members.iterator();
			while(it.hasNext()){
				User user = (User)it.next();
				user.setOrganization(parentOrganization);
				userDAO.update(user);
			}
		}
		organizationDAO.delete(organization);
		return true;
	}

	@Override
	public void deleteResource(long resourceId) {
		resourceDAO.delete(resourceId);
	}

	@Override
	public boolean modifyUser(UserDTO userDTO) throws MessageException {
		User user = userDAO.get(userDTO.getUserId());
		
		DataValidation.isNullOrBlank(userDTO.getUserCode(), "用户编号不能为空");
		DataValidation.isNullOrBlank(userDTO.getUserName(), "用户名不能为空");
		DataValidation.isNullOrBlank(userDTO.getState(), "用户状态不能为空");
		if (!user.getUserName().equals(userDTO.getUserName())) {
			if (userDAO.findUniqueBy("userName", userDTO.getUserName()) != null) {
				throw new MessageException("用户名无效，用户名已经存在");
			}
		}
		if (!user.getUserCode().equals(userDTO.getUserCode())) {
			if (userDAO.findUniqueBy("userCode", userDTO.getUserCode()) != null) {
				throw new MessageException("用户编号无效， 用户编号以及存在");
			}
		}
		DataValidation.isPhoneNumber(userDTO.getMobilePhone(), "无效的手机号码");
		DataValidation.isPhoneNumber(userDTO.getPhone(), "无效的电话号码");
		DataValidation.isEmail(userDTO.getEmailAddress(), "无效的Email地址");
		
		UserDTO.dto2entity(userDTO, user);
		userDAO.update(user);
		return true;
	}

	@Override
	public boolean modifyRole(RoleDTO roleDTO) throws MessageException {
	
		DataValidation.isNullOrBlank(roleDTO.getRoleCode(), "角色编号不能为空");
		DataValidation.isNullOrBlank(roleDTO.getRoleName(), "角色名不能为空");
		Role role = roleDAO.get(roleDTO.getRoleId());
		RoleDTO.dto2entity(roleDTO, role);
		roleDAO.update(role);
		return true;
	}

	@Override
	public void modifyOrganization(OrganizationDTO organizationDTO) throws MessageException {
		Organization organization = 
				organizationDAO.get(organizationDTO
				.getOrganizationId());
		OrganizationDTO.dto2entity(organizationDTO, organization);
		
		DataValidation.isNullOrBlank(organization.getOrganizationCode(),"组织结构编号不能为空");
		DataValidation.isNullOrBlank(organization.getName(),"组织结构名称不能为空");
		DataValidation.isPhoneNumber(organization.getTelephone(), "电话号码无效");
		DataValidation.isPhoneNumber(organization.getFax(), "传真号码无效");
		
		Organization parent = organizationDAO.get(
				organizationDTO.getParentOrganizationId());
		organization.setParent(parent);
		organizationDAO.update(organization);
	}

	@Override
	public void modifyResource(ResourceDTO resourceDTO) {
		Resource resource = resourceDAO.get(
				resourceDTO.getResourceId());
		ResourceDTO.dto2entity(resourceDTO, resource);
		resourceDAO.update(resource);
	}

	@Override
	public Pager<UserDTO> findUsers(int pageNumber, int pageSize) {
		Pager<User> pager = userDAO.findUsers(pageNumber, pageSize);
		Pager<UserDTO> dist = new Pager<UserDTO>();
		List<UserDTO> lisetDTO = new LinkedList<UserDTO>();
		if (pager != null && pager.getTotalCount() != 0) {
			List<User> list = pager.getData();
			for (int i = 0; i < list.size(); i++) {
				UserDTO userDTO = new UserDTO();
				UserDTO.entity2dto(list.get(i), userDTO);
				lisetDTO.add(userDTO);
			}
			dist.setPageNumber(pager.getPageNumber());
			dist.setPageSize(pager.getPageSize());
			dist.setTotalCount(pager.getTotalCount());
			dist.setData(lisetDTO);
		}
		
		return dist;
	}

	@Override
	public List<UserDTO> findUsers(UserQueryConditionDTO queryConditionDTO) {
		List<User> list = userDAO.findUsers(queryConditionDTO);
		List<UserDTO> dist = new LinkedList<UserDTO>();
		if (list != null) {
			for (int i = 0; i < list.size(); i++) {
				UserDTO userDTO = new UserDTO();
				UserDTO.entity2dto(list.get(i), userDTO);
				dist.add(userDTO);
			}
		}
		return dist;
	}

	@Override
	public Pager<UserDTO> findUsers(UserQueryConditionDTO queryConditionDTO,
			int pageNumber, int pageSize) {
		Pager<User> pager = userDAO.findUsers(queryConditionDTO, pageNumber,
				pageSize);
		Pager<UserDTO> dist = new Pager<UserDTO>();
		List<UserDTO> lisetDTO = new LinkedList<UserDTO>();
		if (pager != null && pager.getTotalCount() != 0) {
			List<User> list = pager.getData();
			for (int i = 0; i < list.size(); i++) {
				UserDTO userDTO = new UserDTO();
				User u = list.get(i);
				UserDTO.entity2dto(u, userDTO);
				lisetDTO.add(userDTO);
			}
			dist.setPageNumber(pager.getPageNumber());
			dist.setPageSize(pager.getPageSize());
			dist.setTotalCount(pager.getTotalCount());
			dist.setData(lisetDTO);
		}
		return dist;
	}

	@Override
	public Pager<RoleDTO> findRoles(int pageNumber, int pageSize) {
		Pager<Role> pager = roleDAO.findRoles(pageNumber, pageSize);
		Pager<RoleDTO> dist = new Pager<RoleDTO>();
		List<RoleDTO> lisetDTO = new LinkedList<RoleDTO>();
		if (pager != null && pager.getTotalCount() != 0) {
			List<Role> list = pager.getData();
			for (int i = 0; i < list.size(); i++) {
				RoleDTO roleDTO = new RoleDTO();
				RoleDTO.entity2dto(list.get(i), roleDTO);
				lisetDTO.add(roleDTO);
			}
			dist.setPageNumber(pager.getPageNumber());
			dist.setPageSize(pager.getPageSize());
			dist.setTotalCount(pager.getTotalCount());
			dist.setData(lisetDTO);
		}
		
		return dist;
	}

	@Override
	public List<RoleDTO> findRoles(RoleQueryConditionDTO queryConditionDTO) {
		List<Role> list = roleDAO.findRoles(queryConditionDTO);
		List<RoleDTO> dist = new LinkedList<RoleDTO>();
		if (list != null) {
			for (int i = 0; i < list.size(); i++) {
				RoleDTO roleDTO = new RoleDTO();
				RoleDTO.entity2dto(list.get(i), roleDTO);
				dist.add(roleDTO);
			}
		}
		return dist;
	}

	@Override
	public Pager<RoleDTO> findRoles(RoleQueryConditionDTO queryConditionDTO,
			int pageNumber, int pageSize) {
		Pager<Role> pager = roleDAO.findRoles(queryConditionDTO, pageNumber,
				pageSize);
		Pager<RoleDTO> dist = new Pager<RoleDTO>();
		List<RoleDTO> lisetDTO = new LinkedList<RoleDTO>();
		if (pager != null && pager.getTotalCount() != 0) {
			List<Role> list = pager.getData();
			for (int i = 0; i < list.size(); i++) {
				RoleDTO userDTO = new RoleDTO();
				Role u = list.get(i);
				RoleDTO.entity2dto(u, userDTO);
				lisetDTO.add(userDTO);
			}
			dist.setPageNumber(pager.getPageNumber());
			dist.setPageSize(pager.getPageSize());
			dist.setTotalCount(pager.getTotalCount());
			dist.setData(lisetDTO);
		}
		
		return dist;
	}

	@Override
	public UserDTO loadUser(Serializable userId) {
		UserDTO userDTO = new UserDTO();
		User user = userDAO.load(userId);
		UserDTO.entity2dto(user, userDTO);
		return userDTO;
	}

	@Override
	public OrganizationDTO loadOrganization(Serializable organizationId) {
		Organization organization = organizationDAO
				.get(organizationId);
		OrganizationDTO dto = new OrganizationDTO();
		OrganizationDTO.entity2dto(organization, dto);
		return dto;
	}

	@Override
	public boolean distributeRoles(Serializable userId,
			List<Serializable> roleId) {

		return true;
	}

	@Override
	public boolean changePasswordDefault(Long userId) {
		User user = userDAO.load(userId);
		user.setPassword("123456");
		userDAO.update(user);
		return true;
	}

	@Override
	public Node findOrganizationReturnTree() {
		Organization rootOrganization = 
				organizationDAO.findRootOrganization();
		Node root = new Node();
		if(rootOrganization != null)
			root.setId(rootOrganization.getId());
			root.setText(rootOrganization.getName());
			organization2Tree(root,rootOrganization);
		return root;
	}
	
	private void findOrganizationMember(Organization organization,
			Set<User> childs) {
		Iterator<Organization> iterator = organization.getChilds().iterator();
		if (iterator != null) {
			while (iterator.hasNext()) {
				Organization o = iterator.next();
				childs.addAll(o.getMember());
				o.getMember().clear();
				findOrganizationMember(o, childs);
				organizationDAO.update(o);
			}
		}
	}
	
	private void organization2Tree(Node root, 
			Organization rootOrganization){
		Set<Organization> children = rootOrganization.getChilds();
		if(children != null && children.size() != 0){
			root.setLeaf(false);
			Iterator<Organization> it = children.iterator();
			while (it.hasNext()) {
				Organization organization = (Organization) it.next();
				Node node = new Node(organization.getId()
						,root.getId(),organization.getName());
				root.getChildren().add(node);
				organization2Tree(node,organization);
			}
		}else{
			root.setLeaf(true);
		}
	}

	@Override
	public Pager<UserDTO> findUsersByOrganizationId(long organization, int page, int limit) {
		Pager<User> pager = userDAO.findUsersByOrganizationId(organization, page, limit);
		Pager<UserDTO> dist = new Pager<UserDTO>();
		List<UserDTO> lisetDTO = new LinkedList<UserDTO>();
		if (pager != null && pager.getTotalCount() != 0) {
			List<User> list = pager.getData();
			for (int i = 0; i < list.size(); i++) {
				UserDTO userDTO = new UserDTO();
				User u = list.get(i);
				UserDTO.entity2dto(u, userDTO);
				lisetDTO.add(userDTO);
			}
			dist.setPageNumber(pager.getPageNumber());
			dist.setPageSize(pager.getPageSize());
			dist.setTotalCount(pager.getTotalCount());
			dist.setData(lisetDTO);
		}
		return dist;
	}

	@Override
	public Pager<OrganizationDTO> findOrganizations(int pageNumber, int pageSize) {
		Pager<Organization> pager = organizationDAO.findOrganizations(pageNumber,pageSize);
		Pager<OrganizationDTO> dist = new Pager<OrganizationDTO>();
		List<OrganizationDTO> lisetDTO = new LinkedList<OrganizationDTO>();
		if (pager != null && pager.getTotalCount() != 0) {
			List<Organization> list = pager.getData();
			for (int i = 0; i < list.size(); i++) {
				OrganizationDTO OrganizationDTO = new OrganizationDTO();
				Organization organization = list.get(i);
				OrganizationDTO.entity2dto(organization, OrganizationDTO);
				lisetDTO.add(OrganizationDTO);
			}
			dist.setPageNumber(pager.getPageNumber());
			dist.setPageSize(pager.getPageSize());
			dist.setTotalCount(pager.getTotalCount());
			dist.setData(lisetDTO);
		}
		return dist;
	}
}